package cn.tristenstudy.blog.service.impl;

import cn.tristenstudy.blog.exception.MyNotFoundException;
import cn.tristenstudy.blog.mapper.BlogMapper;
import cn.tristenstudy.blog.mapper.BlogTagMapper;
import cn.tristenstudy.blog.mapper.TagMapper;
import cn.tristenstudy.blog.mapper.UserMapper;
import cn.tristenstudy.blog.pojo.Blog;
import cn.tristenstudy.blog.pojo.BlogTag;
import cn.tristenstudy.blog.pojo.Tag;
import cn.tristenstudy.blog.pojo.User;
import cn.tristenstudy.blog.pojo.vo.BlogQuery;
import cn.tristenstudy.blog.service.BlogService;
import cn.tristenstudy.blog.util.MarkDownUtils;
import cn.tristenstudy.blog.util.RedisUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author xichen1.li
 * @date 2020-12-29 15:02
 */
@Service
@Transactional
public class BlogServiceImpl implements BlogService {

    @Autowired
    BlogMapper blogMapper;
    @Autowired
    BlogTagMapper blogTagMapper;
    @Autowired
    TagMapper tagMapper;
    @Autowired
    UserMapper userMapper;

    @Autowired
    @Qualifier("myRedisTemplate")
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    RedisUtil redisUtil;

    @Override
    public Blog getBlog(Long id) {
        Blog blog = blogMapper.selectById(id);
        QueryWrapper<BlogTag> queryWrapper = new QueryWrapper<>();
        BlogTag blogTag = new BlogTag();
        blogTag.setBlogId(blog.getId());
        queryWrapper.setEntity(blogTag);
        List<BlogTag> blogTags = blogTagMapper.selectList(queryWrapper);
        StringBuilder stringBuffer = new StringBuilder();
        for (BlogTag tag : blogTags) {
            stringBuffer.append(tag.getTagId()).append(",");
        }
        blog.setTagIds(stringBuffer.toString());
        return blog;
    }

    @Override
    public Blog selectById(Long id) {
        Blog blog = blogMapper.selectById(id);
        if (blog == null) {
            throw new MyNotFoundException("该博客不存在！");
        }
        redisUtil.incr(String.valueOf(id),1);
        blog.setViews((Integer) redisUtil.get(String.valueOf(id)));
        blogMapper.updateById(blog);
        String content = blog.getContent();
        String htmlExtensions = MarkDownUtils.markDownToHtmlExtensions(content);
        QueryWrapper<User> userQuery = new QueryWrapper<>();
        userQuery.eq("id", blog.getUserId());
        userQuery.select("nickname", "avatar");
        User user = userMapper.selectOne(userQuery);
        QueryWrapper<BlogTag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("blog_id", blog.getId());
        List<BlogTag> blogTags = blogTagMapper.selectList(queryWrapper);
        StringBuilder stringBuffer = new StringBuilder();
        for (BlogTag tag : blogTags) {
            stringBuffer.append(tag.getTagId()).append(",");
        }
        QueryWrapper<Tag> tagQueryWrapper = new QueryWrapper<>();
        tagQueryWrapper.eq("del_flag", 0);
        tagQueryWrapper.in("id", stringBuffer.toString());
        List<Tag> tagList = tagMapper.selectList(tagQueryWrapper);
        blog.setTagList(tagList);
        blog.setUser(user);
        blog.setContent(htmlExtensions);
        return blog;
    }

    @Override
    public Page<Blog> listBlog(BlogQuery query) {
        query.setSize(5);
        return blogMapper.listBlog(query);
    }

    @Override
    public Page<Blog> listBlog(Integer current) {
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User) subject.getPrincipal();
        BlogQuery query = new BlogQuery();
        query.setCurrent(current);
        if (currentUser == null) {
            query.setPublished(true);
        }
        return blogMapper.listBlog(query);
    }

    @Override
    public List<Blog> listRecommendBlogTop(Integer size) {
        QueryWrapper<Blog> query = new QueryWrapper<>();
        query.select("id", "title");
        query.eq("del_flag", 0);
        query.eq("recommend", true);
        query.eq("published", true);
        query.orderByDesc("create_time");
        List<Blog> blogList = blogMapper.selectList(query);
        return blogList.stream()
                .limit(size)
                .collect(Collectors.toList());
    }

    @Transactional
    @Override
    public Boolean saveBlog(Blog blog) {
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User) subject.getPrincipal();
        String tagIds = blog.getTagIds();
        if (blog.getId() != null) {
            blog.setUpdateTime(new Date());
            blog.setTagIds(null);
            int update = blogMapper.updateById(blog);
            QueryWrapper<BlogTag> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("blog_id", blog.getId());
            blogTagMapper.delete(queryWrapper);
            insertBlogTag(tagIds, blog);
            return update > 0;
        }
        //获取当前用户
        blog.setUserId(currentUser.getId());
        blog.setCreateTime(new Date());
        blog.setUpdateTime(new Date());
        blog.setViews(0);
        blog.setTagIds(null);
        int insert = blogMapper.insert(blog);
        insertBlogTag(tagIds, blog);
        return insert > 0;
    }

    @Transactional
    @Override
    public Boolean updateBlog(Blog blog) {
        Blog select = blogMapper.selectById(blog.getId());
        if (select == null) {
            throw new MyNotFoundException("博客不存在！");
        }
        blog.setUpdateTime(new Date());
        int update = blogMapper.updateById(blog);
        return update > 0;
    }

    @Transactional
    @Override
    public Boolean deleteBlog(Long id) {
        Blog blog = blogMapper.selectById(id);
        if (blog == null) {
            throw new MyNotFoundException("博客不存在！");
        }
        blog.setUpdateTime(new Date());
        blog.setDelFlag(1);
        QueryWrapper<BlogTag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("blog_id", blog.getId());
        blogTagMapper.delete(queryWrapper);
        int update = blogMapper.updateById(blog);
        return update > 0;
    }

    @Override
    public Map<String, List<Blog>> archiveBlog() {
        HashMap<String, List<Blog>> hashMap = new HashMap<>();
        List<String> list = blogMapper.queryYearGroup();
        for (String year : list) {
            List<Blog> blogList = blogMapper.queryBlogByYear(year);
            hashMap.put(year, blogList);
        }
        return hashMap;
    }

    @Override
    public Integer getBlogCount() {
        QueryWrapper<Blog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("del_flag", 0);
        queryWrapper.eq("published", true);
        return blogMapper.selectCount(queryWrapper);
    }

    /**
     * 处理多对多映射
     *
     * @param tagIds 标签id
     * @param blog   博客
     */
    public void insertBlogTag(String tagIds, Blog blog) {
        if (StringUtils.hasLength(tagIds)) {
            String[] tagArr = tagIds.split(",");
            for (String tagId : tagArr) {
                if (StringUtils.hasLength(tagId)) {
                    BlogTag blogTag = new BlogTag();
                    blogTag.setBlogId(blog.getId());
                    blogTag.setPublished(blog.isPublished());
                    blogTag.setTagId(Long.valueOf(tagId));
                    blogTagMapper.insert(blogTag);
                }
            }
        }
    }
}
